Skip to content

fix: preserve vertex attributes with smooth normals - #9233

Merged
davepagurek merged 10 commits into
processing:mainfrom
Srinidhi444:fix/smooth-normals-preserve-attributes
Oct 8, 2026
Merged

davepagurek merged 10 commits into
processing:mainfrom
Srinidhi444:fix/smooth-normals-preserve-attributes

Conversation

@Srinidhi444

Copy link
Copy Markdown
Contributor

Resolves #9205

Changes:

  • Fixed computeNormals(SMOOTH) so it no longer permanently deduplicates geometry vertices based only on position.
  • Smooth normals are calculated using temporary position-based vertex groups and then mapped back to the original vertices.
  • This preserves per-vertex attributes such as UVs while still allowing vertices at the same position to share smooth normals.
  • Added a unit test covering vertices with the same position but different UV coordinates.

Screenshots of the change:
image

PR Checklist

@p5-bot

p5-bot Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

@davepagurek davepagurek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic looks good! To confirm that the normals themselves haven't changed since before, would you be up for adding a visual test with maybe normalMaterial() on a shape with computeNormals(SMOOTH) applied so that we can more easily visually inspect it? If you need some example geometry, there's an example sketch in the "smooth shading" section of https://p5js.org/tutorials/custom-geometry/ that we could borrow.

Comment thread src/webgl/p5.Geometry.js
uniqueVertices.push(vertex);
}

originalToUnique[i] = vertexIndices[key];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

@Srinidhi444

Copy link
Copy Markdown
Contributor Author

Logic looks good! To confirm that the normals themselves haven't changed since before, would you be up for adding a visual test with maybe normalMaterial() on a shape with computeNormals(SMOOTH) applied so that we can more easily visually inspect it? If you need some example geometry, there's an example sketch in the "smooth shading" section of https://p5js.org/tutorials/custom-geometry/ that we could borrow.

Logic looks good! To confirm that the normals themselves haven't changed since before, would you be up for adding a visual test with maybe normalMaterial() on a shape with computeNormals(SMOOTH) applied so that we can more easily visually inspect it? If you need some example geometry, there's an example sketch in the "smooth shading" section of https://p5js.org/tutorials/custom-geometry/ that we could borrow.

sure

@Srinidhi444

Copy link
Copy Markdown
Contributor Author

Logic looks good! To confirm that the normals themselves haven't changed since before, would you be up for adding a visual test with maybe normalMaterial() on a shape with computeNormals(SMOOTH) applied so that we can more easily visually inspect it? If you need some example geometry, there's an example sketch in the "smooth shading" section of https://p5js.org/tutorials/custom-geometry/ that we could borrow.

hey @davepagurek added the requested visual test for computeNormals(SMOOTH) using normalMaterial() on the warped tube geometry from the smooth shading example.
The visual test passes and the expected screenshot has been generated pls check it and let me know if any issues
image

@davepagurek

Copy link
Copy Markdown
Contributor

Hi @Srinidhi444! When you add visual tests, you have to run them locally and commit the image files that get added to the project. The idea is that those images remain checked into source control so that when future changes happen, the tests are rerun and compared to those images to make sure that nothing breaks.

@Srinidhi444

Srinidhi444 commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Hi @Srinidhi444! When you add visual tests, you have to run them locally and commit the image files that get added to the project. The idea is that those images remain checked into source control so that when future changes happen, the tests are rerun and compared to those images to make sure that nothing breaks.

hey @davepagurek my bad didn't knew that i have committed the necessary changes let me know if they are correct.

@davepagurek

Copy link
Copy Markdown
Contributor

Hmm when I run the tests on CI, it says it expected this:
image

but received this:
image

Any idea where the difference comes from? Do you get that when running it locally?

@Srinidhi444

Copy link
Copy Markdown
Contributor Author

Hmm when I run the tests on CI, it says it expected this: image

but received this: image

Any idea where the difference comes from? Do you get that when running it locally?
Hey @davepagurek, I found the issue. It was caused by p5.noise() generating a different noise pattern between test runs, which resulted in different radii and therefore different screenshots. I fixed it by setting a fixed noise seed with p5.noiseSeed(0).

@davepagurek davepagurek left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks @Srinidhi444! I think this is good to go.

@davepagurek
davepagurek merged commit 3998034 into processing:main Oct 8, 2026
4 checks passed
@davepagurek

Copy link
Copy Markdown
Contributor

@all-contributors please add @Srinidhi444 for code

@allcontributors

Copy link
Copy Markdown
Contributor

@davepagurek

I've put up a pull request to add @Srinidhi444! 🎉

@davepagurek

Copy link
Copy Markdown
Contributor

@Srinidhi444 are you interested in making follow-up issues for the next steps mentioned in #9205 ? Feel free to do so + also work on them if you're up for it!

@Srinidhi444

Copy link
Copy Markdown
Contributor Author

@Srinidhi444 are you interested in making follow-up issues for the next steps mentioned in #9205 ? Feel free to do so + also work on them if you're up for it!

@davepagurek yes sure i will understand them first properly and then will come with a approach and then will let you know

@Srinidhi444

Copy link
Copy Markdown
Contributor Author

Hey @davepagurek!

I wanted to confirm my understanding of the remaining improvements mentioned in #9205 before creating the follow-up issues.

From what I understand, there are two main changes left:

1. Rename FLAT to KEEP_CONNECTIONS

The first change would be to introduce KEEP_CONNECTIONS for the existing FLAT behavior, while keeping FLAT as a deprecated alias for backward compatibility.

Just wanted to clarify one thing here: is the plan to keep FLAT as a deprecated alias indefinitely, or would we eventually remove it in a future version? Also, should we mark it as deprecated in the documentation for now?

2. Introduce SEGMENTED for true flat shading

The second change would be to implement actual flat shading, which, from my understanding, is somewhat the opposite of what we did for SMOOTH.

My current understanding of the approach is:

  • Calculate the normal of each face separately.
  • Create independent vertices for each triangle so that shared vertices can have different normals.
  • Duplicate the corresponding UVs and other per-vertex attributes to preserve their alignment.
  • Assign each triangle's face normal to its own vertices.
  • Update the face indices to reference the new vertices.

Something like this, if I'm understanding it correctly:

Illustration

3. Selective smoothing / sharp edges

I also saw your suggestion about allowing some edges to remain sharp while others are smoothed, possibly through an additional options object.

I haven't explored this part deeply yet, as I think it would require some more thought and investigation. For now, I was planning to focus on the first two improvements and revisit this later.

Regarding the follow-up issues and PRs:

I was thinking of creating two separate issues and two separate PRs:

  • One for introducing KEEP_CONNECTIONS and deprecating FLAT.
  • Another for implementing SEGMENTED with true flat shading.
    i think that would be clean ,let me know if i have misunderstood something or there is a better approach before creating the issues.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[p5.js 2.0+ Bug Report]: computeNormals(SMOOTH) destroys uv attribute

2 participants